﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using GoldDigger.Models;
using Microsoft.Win32;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate;
using Point = System.Windows.Point;

namespace GoldDigger.Editor
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Point _startPoint;


        public MainWindow()
        {
            InitializeComponent();

            //object testValue = new ParticleSettings();

            //XmlWriterSettings settings = new XmlWriterSettings {Indent = true};
            //using (XmlWriter xmlWriter = XmlWriter.Create("test.xml", settings))
            //{
            //    IntermediateSerializer.Serialize(xmlWriter, testValue, null);
            //}
        }

        private void itemPanel_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // Store the mouse position
            _startPoint = e.GetPosition(null);
        }

        private void itemPanel_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            // Get the current mouse position
            Point mousePos = e.GetPosition(null);
            Vector diff = _startPoint - mousePos;

            if (e.LeftButton == MouseButtonState.Pressed &&
                Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance &&
                Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)
            {
                // Get the dragged ListViewItem
                //StackPanel panel = sender as StackPanel;
                Image item = FindAnchestor<Image>((DependencyObject)e.OriginalSource);

                // Find the data behind the ListViewItem
                var itemType = Item.GetType(item);

                // Initialize the drag & drop operation
                DataObject dragData = new DataObject("ItemType", itemType);
                DragDrop.DoDragDrop(item, dragData, DragDropEffects.Move);
            }
        }

        // Helper to search up the VisualTree
        private static T FindAnchestor<T>(DependencyObject current)
            where T : DependencyObject
        {
            do
            {
                if (current is T)
                {
                    return (T)current;
                }
                current = VisualTreeHelper.GetParent(current);
            }
            while (current != null);
            return null;
        }


        private void canvasScene_Drop(object sender, DragEventArgs e)
        {
            var pos = e.GetPosition(canvasScene);
            AddNewItem((ItemType)e.Data.GetData("ItemType"), pos.X, pos.Y);
        }

        private void AddNewItem(ItemType itemType, double x, double y)
        {
            var style = Resources[itemType.ToString()] as Style;
            if (style == null)
                throw new ApplicationException("Missing style definition for item type " + itemType);
            var newItem = new Image { Style = style };
            Canvas.SetLeft(newItem, x - newItem.Width / 2);
            Canvas.SetTop(newItem, y - newItem.Height / 2);
            Item.SetType(newItem, itemType);
            canvasScene.Children.Add(newItem);
        }

        private void canvasScene_DragEnter(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent("ItemType") || sender == e.Source)
            {
                e.Effects = DragDropEffects.None;
            }
        }


        private Scene _scene = new Scene();

        private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            _scene = new Scene();
            canvasScene.AllowDrop = true;
            ClearItems();
        }
        
        private void SaveCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Scene file (*.xml)|*.xml";
            if (saveFileDialog.ShowDialog() == true)
            {
                _scene.ItemSprites = (from i in canvasScene.Children.Cast<UIElement>().OfType<Image>()
                                      let t = Item.GetType(i)
                                      where t != ItemType.None
                                      select new Models.Item
                                                 {
                                                     Type = t,
                                                     X = (float)(Canvas.GetLeft(i) + i.Width / 2),
                                                     Y = (float)(Canvas.GetTop(i) + i.Height / 2),
                                                 }).ToArray();
                XmlWriterSettings settings = new XmlWriterSettings { Indent = true };
                using (XmlWriter xmlWriter = XmlWriter.Create(saveFileDialog.FileName, settings))
                {
                    IntermediateSerializer.Serialize(xmlWriter, _scene, null);
                }
            }
        }

        private void OpenCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Scene file (*.xml)|*.xml";
            if(openFileDialog.ShowDialog() == true)
            {
                using (XmlReader xmlReader = XmlReader.Create(openFileDialog.FileName))
                {
                    _scene = IntermediateSerializer.Deserialize<Scene>(xmlReader, openFileDialog.FileName + "t");
                }
                ClearItems();
                foreach (var i in _scene.ItemSprites)
                    AddNewItem(i.Type, i.X, i.Y);
            }
        }

        void ClearItems()
        {
            var items = (from i in canvasScene.Children.Cast<UIElement>().OfType<Image>()
                         let t = Item.GetType(i)
                         where t != ItemType.None
                         select i).ToArray();
            foreach (var i in items)
                canvasScene.Children.Remove(i);
        }
    }
}
